﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WisDom.DBContext;
using WisDom.IService;
using WisDom.Util;
using WisDom.Util.Extension;
using WisDom.Utils;
using Microsoft.Extensions.Options;
using System.Data.Common;
using System.Data.SqlClient;
using MySql.Data.MySqlClient;
using Microsoft.Data.Sqlite;
namespace WisDom.Services
{

    public abstract class BaseService<T> where T : class, new()
    {
        private readonly ApplicationDbContext _dbContext;
        private readonly DbContextOption _dbContextOption;
        private readonly DbSet<T> _set;
        public BaseService(ApplicationDbContext dbContext, IOptions<DbContextOption> dbContextOption)
        {
            if (dbContext == null) throw new ArgumentNullException(nameof(dbContext));
            _dbContext = dbContext;
            _dbContextOption = dbContextOption.Value;
            _dbContext.Database.EnsureCreated();
            _set = dbContext.Set<T>();
        }


        #region 公共查询条件

        protected virtual Expression<Func<T, bool>> TrueCondition(string queryJson)
        {
            return n => 1 == 1;
        }



        #endregion

        #region 获取数据
        /// <summary>
        /// 获取数据列表
        /// </summary>
        /// <param name="queryJson">查询条件</param>
        /// <returns></returns>
        public virtual async Task<List<T>> GetList(string queryJson)
        {
            return await _set.Where(TrueCondition(queryJson)).ToListAsync();
        }

        /// <summary>
        /// 通过linq表达式获取数据
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual async Task<List<T>> GetList(Expression<Func<T, bool>> @where = null)
        {
            if (@where == null)
            {
                return await _set.ToListAsync();
            }
            else
            {
                return await _set.Where(@where).ToListAsync();
            }
        }


        /// <summary>
        /// 获取分页的数据列表
        /// </summary>
        /// <param name="pagination">分页对象</param>
        /// <param name="queryJson">查询条件</param>
        /// <returns></returns>
        public virtual async Task<List<T>> GetPageList(Pagination pagination, string queryJson)
        {
            var qry = _set.Where(TrueCondition(queryJson)).Skip(pagination.Skip).Take(pagination.Take);
            pagination.Records = _set.Where(TrueCondition(queryJson)).Count();
            return await qry.ToListAsync();
        }

        /// <summary>
        /// 获取分页的DataTable
        /// </summary>
        /// <param name="pagination">分页对象</param>
        /// <param name="queryJson">查询条件</param>
        /// <returns></returns>
        public Task<DataTable> GetBaseDataTable(string sql)
        {
            return Task.Run<DataTable>(() =>
            {
                using (var dbCon = _dbContext.Database.GetDbConnection())
                {
                    DbDataAdapter da = null;
                    switch (_dbContextOption.DbType)
                    {
                        case DBContext.DbType.MYSQL:
                            da = new MySqlDataAdapter(sql, dbCon as MySqlConnection);
                            break;
                        default:
                            da = new SqlDataAdapter(sql, dbCon as SqlConnection);
                            break;
                    }
                    DataTable dt = new DataTable();
                    da.Fill(dt);
                    return dt;
                }
            });
        }

        /// <summary>
        /// 获取分页的DataTable
        /// </summary>
        /// <param name="pagination">分页对象</param>
        /// <param name="queryJson">查询条件</param>
        /// <returns></returns>
        public Task<DataTable> GetBasePageData(Pagination pagination, string sql)
        {
            return Task.Run<DataTable>(() =>
             {
                 using (var dbCon = _dbContext.Database.GetDbConnection())
                 {
                     DbDataAdapter da = null;
                     switch (_dbContextOption.DbType)
                     {
                         case DBContext.DbType.MYSQL:
                             da = new MySqlDataAdapter(sql, dbCon as MySqlConnection);
                             break;
                         default:
                             da = new SqlDataAdapter(sql, dbCon as SqlConnection);
                             break;
                     }
                     DataTable dt = new DataTable();
                     da.Fill(dt);
                     return dt;
                 }
             });
        }

        /// <summary>
        /// 获取单个实体
        /// </summary>
        /// <param name="keyValue">主键值</param>
        /// <returns></returns>
        public Task<T> GetSingle(Expression<Func<T, bool>> @where = null)
        {
            if (@where == null) return _set.SingleOrDefaultAsync();
            return _set.SingleOrDefaultAsync(@where);
        }

        #endregion

        #region 保存数据
        /// <summary>
        /// 新增数据
        /// </summary> 
        /// <returns></returns>
        public async Task<bool> InsertData(T entity)
        {
            _set.Add(entity);
            return await _dbContext.SaveChangesAsync() > 0 ? true : false;
        }
        /// <summary>
        /// 更新数据
        /// </summary> 
        /// <returns></returns>
        public async Task<bool> UpdateData(T entity)
        {
            _dbContext.Edit<T>(entity);
            return await _dbContext.SaveChangesAsync() > 0 ? true : false;
        }


        /// <summary>
        /// 移除数据
        /// </summary>
        /// <param name="keyValue"></param>
        /// <returns></returns>
        public async Task RemoveData(Expression<Func<T, bool>> @where)
        {
            var entity = await GetList(@where);
            if (entity != null)
            {
                _set.RemoveRange(entity);
                await _dbContext.SaveChangesAsync();
            }
        }
        #endregion 
    }
}
